

<template>
  <div class="app-container calendar-list-container">
    <basic-container>
      <avue-crud
        ref="crud"
        :option="tableOption"
        :data="list"
        :page.sync="page"
        v-model="form"
        :table-loading="listLoading"
        @on-load="getList"
        @search-change="handleFilter"
        @refresh-change="handleRefreshChange"
        @row-update="update"
        @row-save="create">
        <template slot-scope="{type,disabled}" slot="codeForm">
          <el-input :disabled="disabled" v-model="form.code">
            <template slot="prepend"><span v-if="type=='add'">{{ROLE_PREFIX}}</span></template>
          </el-input>
        </template>
        <template slot="menuLeft">
          <el-button
            v-if="permissions.sys_role_add"
            class="filter-item"
            type="primary"
            icon="el-icon-edit"
            @click="$refs.crud.rowAdd()">添加
          </el-button>
          <el-button
            v-if="permissions.sys_role_import_export"
            class="filter-item"
            plain
            type="primary"
            size="small"
            icon="el-icon-upload"
            @click="$refs.excelUpload.show()"
          >导入
          </el-button>
          <el-button
            v-if="permissions.sys_role_import_export"
            class="filter-item"
            plain
            type="primary"
            size="small"
            icon="el-icon-download"
            @click="exportExcel"
          >导出
          </el-button>
        </template>

        <template
          slot="menu"
          slot-scope="scope">
          <el-button
            v-if="permissions.sys_role_edit"
            type="text"
            icon="el-icon-edit"
            size="small"
            @click="handleUpdate(scope.row,scope.index)">编辑
          </el-button>
          <el-button
            v-if="permissions.sys_role_perm"
            type="text"
            size="small"
            icon="el-icon-plus"
            @click="handlePermission(scope.row,scope.index)">权限
          </el-button>
          <el-button
            v-if="permissions.sys_role_data"
            type="text"
            size="small"
            icon="el-icon-s-grid"
            @click="handleDataScope(scope.row,scope.index)">数据
          </el-button>
          <el-button
            v-if="permissions.sys_role_del"
            type="text"
            size="small"
            icon="el-icon-delete"
            @click="handleDelete(scope.row,scope.index)">删除
          </el-button>
        </template>
      </avue-crud>

      <!--excel 模板导入 -->
      <excel-upload
        ref="excelUpload"
        title="角色信息导入"
        url="/admin-service/role/import"
        temp-name="角色信息.xlsx"
        temp-url="/admin-service/file/minionfile/role.xlsx"
        @refreshDataList="handleRefreshChange"
      ></excel-upload>
    </basic-container>
    <el-dialog
      :visible.sync="dialogPermissionVisible"
      :close-on-click-modal="false"
      title="分配菜单权限">
      <el-container style="border: 1px solid #eee">
        <el-aside width="200px" style="border-right:1px solid #E9EEF3;">
          <el-table :data="applicationList"  row-key="id" :show-header="false" :row-style="tableRowClassName"
                    @cell-click="clickApplication">
            <el-table-column label="应用平台" min-width="100px" align="left">
              <template slot-scope="scope" >
                <span>{{ scope.row.aliasName}}</span>
                <i v-if="scope.row.isCheck" class="el-icon-check">
                  <span class="checkedLengthClass">
                    ({{scope.row.checkedKeys.length}})
                  </span>
                </i>
              </template>
            </el-table-column>
          </el-table>
        </el-aside>
        <el-container :span="12">
          <el-main>
            <div class="dialog-main-tree">
              <el-tree
                :empty-text="'请您先单击左侧应用'"
                ref="menuTree"
                :data="menuTreeData"
                :default-checked-keys="checkedKeys"
                :check-strictly="false"
                :props="defaultPerProps"
                :filter-node-method="filterNode"
                class="filter-tree"
                @check="checkedChange"
                node-key="id"
                highlight-current
                show-checkbox
                default-expand-all/>
            </div>
          </el-main>
        </el-container>
      </el-container>
      <div slot="footer"
           class="dialog-footer">
        <el-button
          type="primary"
          @click="updatePermission(id)">更 新
        </el-button>
        <el-button
          type="default"
          @click="cancel()">取消
        </el-button>
      </div>
    </el-dialog>

    <el-dialog
      :visible.sync="dialogScopeVisible"
      :close-on-click-modal="false"
      title="分配数据权限">
      <el-container style="border: 1px solid #eee">
        <el-aside width="200px" style="border-right:1px solid #E9EEF3;">
          <el-table :data="applicationList"  row-key="id" :show-header="false" :row-style="tableRowClassName"
                    @cell-click="clickApplication2">
            <el-table-column label="应用平台" min-width="100px" align="left">
              <template slot-scope="scope" >
                <span>{{ scope.row.aliasName}}</span>
                <i v-if="scope.row.isCheck" class="el-icon-check">
                </i>
              </template>
            </el-table-column>
          </el-table>
        </el-aside>
        <el-container :span="12">
          <div v-if="clickAppId===undefined || clickAppId===''" class="el-tree__empty-block"><span class="el-tree__empty-text">请您先单击左侧应用</span></div>
          <el-main v-if="clickAppId!==undefined">
            <el-select v-model="scopeType" placeholder="请选择" clearable @change="changeScope">
              <el-option
                v-for="item in scopeTypeDict"
                :key="item.value"
                :label="item.label"
                :value="item.value">
              </el-option>
            </el-select>
            <div class="dialog-main-tree">
              <el-tree
                :empty-text="'部门组织树为空'"
                v-if="scopeType == 1"
                ref="dataTree"
                :check-strictly="true"
                :data="scopeTreeData"
                :default-checked-keys="checkedScopeKeys"
                :props="defaultScopeProps"
                :filter-node-method="filterNode"
                @check="checkedChange2"
                class="filter-tree"
                node-key="id"
                highlight-current
                show-checkbox
                default-expand-all/>
            </div>
          </el-main>
        </el-container>
      </el-container>

      <div slot="footer"
           class="dialog-footer">
        <el-button
          type="primary"
          @click="updateDataScope(id)">更 新
        </el-button>
        <el-button
          type="default"
          @click="cancel()">取消
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {addObj, delObj, fetchList, fetchRoleTree, permissionUpd,dataScopeUpd, putObj,fetchRoleScope} from '@/api/admin/role'
import {tableOption,ROLE_PREFIX} from '@/const/crud/admin/role'
import {getAllApplications} from '@/api/admin/application'
import {fetchMenuTree} from '@/api/admin/menu'
import {fetchTree} from '@/api/admin/org'
import {mapGetters} from 'vuex'
import ExcelUpload from "@/components/upload/excel";

export default {
  name: 'TableRole',
  components: { ExcelUpload },
  data() {
    return {
      searchForm: {},
      tableOption: tableOption,
      ROLE_PREFIX: ROLE_PREFIX,
      menuTreeData: [],
      scopeTreeData: [],
      checkAppIdList: [],
      applicationList: [{isCheck:false,checkedKeys:new Array()}],
      clickAppId: undefined,
      scopeTypeDict: [
        {
          label: '全部',
          value: 0
        }, {
          label: '自定义',
          value: 1
        }, {
          label: '本级及子级',
          value: 2
        }, {
          label: '本级',
          value: 3
        }
      ],
      scopeType: undefined,
      appIdMenuList:[],
      appIdDataSCopeList:[],
      checkedKeys: [],
      checkedScopeKeys: [],
      checkedDsScope: [],
      defaultPerProps: {
        label: 'name',
        value: 'id'
      },
      defaultScopeProps:{
        label: 'name',
        value: 'id'
      },
      page: {
        total: 0, // 总页数
        currentPage: 1, // 当前页数
        pageSize: 20 // 每页显示多少条
      },
      datas: '',
      list: [],
      listLoading: true,
      form: {},
      id: undefined,
      code: undefined,
      dialogPermissionVisible: false,
      dialogScopeVisible: false,
    }
  },
  computed: {
    ...mapGetters(['elements', 'permissions'])
  },
  created() {
    this.handleApplicationList();
  },
  methods: {
    getList(page, params) {
      this.listLoading = true
      fetchList(Object.assign({
        current: page.currentPage,
        size: page.pageSize
      }, params, this.searchForm)).then(response => {
        this.list = response.data.data.records
        this.page.total = response.data.data.total
        this.listLoading = false
      }).catch(() => {
        this.listLoading = false
      })
    },
    handleApplicationList() {
      getAllApplications().then((res) => {
        this.applicationList = res.data.data;
      })
    },
    clickApplication2(row, column, cell){
      if (this.clickAppId==row.id){
        this.clickAppId=undefined;
        this.checkedKeys=new Array();
        this.menuTreeData=new Array();
      }else {
        this.clickAppId = row.id;
        this.scopeType = row.scopeType;
        //查询右边的树结构
        if (this.scopeType==1){
          this.checkedScopeKeys = row.orgIdList;
        }
      }
    },
    clickApplication(row, column, cell){
      if (this.clickAppId==row.id){
        this.clickAppId=undefined;
        this.checkedKeys=new Array();
        this.menuTreeData=new Array();
      }else {
        this.clickAppId = row.id;
        //查询右边的树结构
        this.handleMenuTree();
        this.checkedKeys = row.checkedKeys;
      }
    },
    tableRowClassName({row}) {
      if (row.id === this.clickAppId) {
        return { 'background-color': '#67C23A', cursor: 'pointer' };
      }
      return { cursor: 'pointer' };
    },
    handleRefreshChange() {
      this.getList(this.page)
    },
    handleFilter(form,done) {
      this.searchForm = form
      this.page.currentPage = 1
      this.getList(this.page, form)
      done();
    },
    handleUpdate(row, index) {
      this.$refs.crud.rowEdit(row, index)
    },
    cancel() {
      this.dialogPermissionVisible = false;
      this.dialogScopeVisible = false;
      this.applicationList.forEach(a=>{
          a.isCheck = false;
          a.scopeType = undefined;
          a.checkedKeys = new Array();
          a.orgIdList = new Array();
      })
      this.appIdMenuList = new Array();
      this.appIdDataSCopeList = new Array();
      this.id = undefined
      this.code = undefined;
      this.clickAppId = undefined;
    },
    handlePermission(row) {
      this.id = row.id
      this.code = row.code
      fetchRoleTree(row.id).then(response => {
        this.appIdMenuList=response.data.data;
        if (this.appIdMenuList){
          this.applicationList.forEach(a=>{
            a.isCheck = false;
            a.checkedKeys = new Array();
            this.appIdMenuList.forEach(item=>{
              if (item.appId===a.id){
                if (item.menuIdList.length>0){
                  a.isCheck = true;
                }
                a.checkedKeys = item.menuIdList;
              }
            })
          });
        }
        this.clickAppId = undefined;
        this.dialogPermissionVisible = true;
      })
    },
    checkedChange(data){
      let c = new Array();
      c = c.concat(this.$refs.menuTree.getCheckedKeys()).concat(this.$refs.menuTree.getHalfCheckedKeys());
      //this.appIdMenuList
      let i = this.appIdMenuList.findIndex(item=>item.appId === this.clickAppId);
      if (i>=0){
        let i_item = this.appIdMenuList[i];
        i_item.menuIdList = c;
        this.$set(this.appIdMenuList,i,i_item);
      }else {
        let item = {'menuIdList':c,'appId':this.clickAppId};
        this.appIdMenuList.push(item);
      }

      let j = this.applicationList.findIndex(item=>item.id === this.clickAppId);
      let j_item = this.applicationList[j];
      j_item.checkedKeys = c;
      j_item.isCheck = c.length!==0;
      this.$set(this.applicationList,j,j_item);
    },
    checkedChange2(data){
      let c = this.$refs.dataTree.getCheckedKeys();
      let i = this.appIdDataSCopeList.findIndex(item=>item.appId === this.clickAppId);
      if (i>=0){
        let i_item = this.appIdDataSCopeList[i];
        i_item.orgIdList = c;
        this.$set(this.appIdDataSCopeList,i,i_item);
      }else {
        let item = {'roleId':this.id,'scopeType':this.scopeType,'appId':this.clickAppId,'orgIdList':c};
        this.appIdDataSCopeList.push(item);
      }

      let j = this.applicationList.findIndex(item=>item.id === this.clickAppId);
      let j_item = this.applicationList[j];
      j_item.orgIdList = c;
      j_item.isCheck = true;
      this.$set(this.applicationList,j,j_item);
    },
    handleMenuTree(){
      fetchMenuTree(false,undefined,this.clickAppId).then(response => {
        this.menuTreeData = response.data.data;
        // 解析出所有的太监节点
        this.checkedKeys = this.resolveAllEunuchNodeId(this.menuTreeData, this.checkedKeys, [])
      })
    },
    handleDataScope(row){
      this.id = row.id;
      this.code = row.code
      fetchRoleScope(row.code).then(response =>{
          this.appIdDataSCopeList = response.data.data;
          if (this.appIdDataSCopeList){
            this.applicationList.forEach(a=>{
              a.isCheck = false;
              a['scopeType'] = undefined;
              a['orgIdList'] = new Array();
              this.appIdDataSCopeList.forEach(item=>{
                if (item.appId===a.id){
                  if (item.scopeType!==''
                    &&item.scopeType!==null){
                    a.isCheck = true;
                  }
                  a.scopeType = item.scopeType;
                  a.orgIdList = item.orgIdList;
                }
              })
            });
          }
          return fetchTree();
        }).then(response => {
          this.dialogScopeVisible = true;
          this.scopeTreeData = response.data.data;
          // 解析出所有的太监节点
          this.clickAppId = undefined;
      })
    },

    /**
     * 解析出所有的太监节点id
     * @param json 待解析的json串
     * @param idArr 原始节点数组
     * @param temp 临时存放节点id的数组
     * @return 太监节点id数组
     */
    resolveAllEunuchNodeId(json, idArr, temp) {
      for (let i = 0; i < json.length; i++) {
        const item = json[i]
        // 存在子节点，递归遍历;不存在子节点，将json的id添加到临时数组中
        if (item.children && item.children.length !== 0) {
          this.resolveAllEunuchNodeId(item.children, idArr, temp)
        } else {
          temp.push(idArr.filter(id => id === item.id))
        }
      }
      return temp
    },
    filterNode(value, data) {
      if (!value) return true;
      return data.label.indexOf(value) !== -1
    },
    getNodeData(data, done) {
      done()
    },
    handleDelete(row, index) {
      if (row.isSys==1){
        this.$message.error('系统内置无法删除')
        return
      }
      this.$confirm('是否确认删除名称为"' + row.name + '"' + '"的数据项?', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(function () {
        return delObj(row.id)
      }).then(() => {
        this.getList(this.page)
        this.$notify.success('删除成功')
      })
    },
    create(row, done, loading) {
      if (this.form.dsType === 1) {
        this.form.dsScope = this.$refs.scopeTree.getCheckedKeys().join(',')
      }
      this.form.code = this.ROLE_PREFIX + this.form.code;
      addObj(this.form).then(() => {
        this.getList(this.page)
        done()
        this.$notify.success('创建成功')
      }).catch(() => {
        loading()
      })
    },
    update(row, index, done, loading) {
      if (this.form.dsType === 1) {
        this.form.dsScope = this.$refs.scopeTree.getCheckedKeys().join(',')
      }
      putObj(this.form).then(() => {
        this.getList(this.page)
        done()
        this.$notify.success('修改成功')
      }).catch(() => {
        loading()
      })
    },
    updatePermission(id) {
      let menuIds = new Array();
      this.applicationList.forEach(item=>{
        menuIds = menuIds.concat(item.checkedKeys);
      })
      permissionUpd(id, menuIds.join(',')).then(() => {
        this.dialogPermissionVisible = false
        this.$store.dispatch('GetMenu', {type: false})
        this.$notify.success('修改成功')
      })
    },
    changeScope(value){
      let i = this.appIdDataSCopeList.findIndex(item=>item.appId === this.clickAppId);
      if (i>=0){
        let i_item = this.appIdDataSCopeList[i];
        i_item.scopeType = value;
        if (i_item.scopeType!==1){
          i_item.orgIdList = new Array();
        }
        this.$set(this.appIdDataSCopeList,i,i_item);
      }else {
        let item = {'roleId':this.id,'scopeType':value,'appId':this.clickAppId,'orgIdList':new Array()};
        this.appIdDataSCopeList.push(item);
      }
      let j = this.applicationList.findIndex(item=>item.id === this.clickAppId);
      let j_item = this.applicationList[j];
      j_item.scopeType = value;
      j_item.isCheck = value!=='';
      this.$set(this.applicationList,j,j_item);
    },
    updateDataScope(id){
      dataScopeUpd(this.appIdDataSCopeList).then(() => {
        this.dialogScopeVisible = false;
        this.$notify.success('修改成功')
      })
    },
    exportExcel() {
      this.downBlobFile("/admin-service/role/export",{}, "role.xlsx");
    }
  }
}
</script>
<style lang="scss" scoped>
  .checkedLengthClass{
    color: #1989fa;
    font-size: small;
    vertical-align: middle;
  }
  ::v-deep .el-table tbody tr:hover > td.el-table__cell {
    background-color: transparent !important;
  }
  .el-icon-check{
    color:#1989fa;
    font-size: 20px;
    font-weight: 600;
    float: right;
  }
  .el-dialog__wrapper {
  .el-dialog {
    width: 61% !important;

    .dialog-main-tree {
      max-height: 400px;
      overflow-y: auto;
    }
  }

  .el-form-item__label {
    width: 20% !important;
    padding-right: 20px;
  }

  .el-form-item__content {
    margin-left: 20% !important;
  }
}
</style>
